﻿using System;
using System.Collections.Generic;
using CI;
using CI.Interfaces;
using CI.Organism;

namespace Mesopotamia.SystemTests
{
    /// <summary>
    /// Single Organism with no reproduction
    /// </summary>
    public class SingleOrganismNoRepoduction : IDAL
    {
        protected IDNA _dna = new DNA();
        protected IOrganismCollection _organisms = new CI.Organism.OrganismCollection();
        protected IOrganism _organism;
        protected IChromosomeCollection _chromosomes = new ChromosomeCollection();
        protected IChromosome _chromosome = new Chromosome(Guid.NewGuid());
        protected IChromosome _chromosomeCellular = new Chromosome(Guid.NewGuid());
        protected IChromosome _chromosomeReproduction = new Chromosome(Guid.NewGuid());
        protected IGeneCollection _genesCellular = new GeneCollection();
        protected IGeneCollection _genesReproductive = new GeneCollection();
        protected IGeneCollection _genes = new GeneCollection();
        protected GeneCellular _geneCreate;
        protected GeneCellular _geneDestory;
        protected GeneReproductionAsexual _geneASexual;
        protected IRequirementCollection _requirementsCreate = new RequirementCollection();
        protected IRequirementCollection _requirementsDestroy = new RequirementCollection();
        protected IRequirementCollection _requirementsASexual = new RequirementCollection();
        protected IRequirement _requirementBodyCreate = null;
        protected IRequirement _requirementBodyDestory = null;
        protected IRequirement _requirementASexual = null;
        protected IPhysical _body = null;
        protected ICellCollection _cells = new CellCollection();
        protected Int64 _AmoebaEnergy = 250;
        private readonly SimEnv _simEnv = SimEnv.Instance;

        /// <summary>
        /// Load the organisms out of the database
        /// </summary>
        /// <param name="environment">Environment name to load</param>
        /// <param name="hostEnvironment"></param>
        /// <param name="maxLoadCount"></param>
        /// <param name="selectedOrganismsToLoad"></param>
        /// <returns>Organisms</returns>
        public virtual IHostingEnvironment LoadHostingEnvironment(string environment, IHostingEnvironment hostEnvironment, int maxLoadCount, List<Guid> selectedOrganismsToLoad)
        {
            _simEnv.TraceLogger.LogDebug("Loading Organisms - Start");

            _organism = new CI.Organism.Organism(hostEnvironment, new Guid(), _AmoebaEnergy, 0);

            _geneCreate = new GeneCellular(_organism, Guid.NewGuid());
            _geneDestory = new GeneCellular(_organism, Guid.NewGuid());

            // add the cell collection
            _organism.Cells = _cells;
            // create dna structure
            _organism.DNA = _dna;
            // setup the chromosome collection
            _organism.DNA.Chromosomes = _chromosomes;
            // add a chromosome
            _chromosomes.Add(_chromosome);
            // add a gene collection
            _chromosome.Genes = _genes;


            #region Gene to Create childOrganism
            // add a gene to create the childOrganism
            _genes.Add(_geneCreate);
            // tell the gene who the childOrganism is
            _geneCreate.Organism = _organism;
            // add a requirement colleciton to that gene
            _geneCreate.Requirements = _requirementsCreate;
            // create a body to start after the first heart beat
            _requirementBodyCreate = new HBOffsetTime(_organism, 1, ComparisonType.Equal, Guid.NewGuid());
            // add a body as this is the first step
            _requirementsCreate.Add(_requirementBodyCreate);
            // set the action type as adding
            _geneCreate.ActionType = ActionType.AddCell;
            // create the pysical body
            _body = new Amoeba(_organism, Guid.NewGuid());
            // set the gene's cell
            _geneCreate.Cell = _body;
            #endregion

            #region gene to Destory childOrganism
            // add a gene to create the childOrganism
            _genes.Add(_geneDestory);
            // tell the gene who the childOrganism is
            _geneDestory.Organism = _organism;
            // add a requirement colleciton to that gene
            _geneDestory.Requirements = _requirementsDestroy;
            // destroy the body after the second heart beat
            _requirementBodyDestory = new HBOffsetTimeCell(_organism, 5, _body, ComparisonType.Equal, Guid.NewGuid());
            // add a body as this is the first step
            _requirementsDestroy.Add(_requirementBodyDestory);
            // set the action type as adding
            _geneDestory.ActionType = ActionType.DelCell;
            // set the gene's cell
            _geneDestory.Cell = _body;
            #endregion

            // as we want the childOrganism to grow from dna the nerual system will be empty
            _simEnv.TraceLogger.LogDebug("Set Empty Nerual System");
            _organism.NeuralSystem = null;

            // set alive organisms
            _organisms.AliveAdd(_organism);

            // set the dead organisms
            _organisms.Dead.Clear();

            // tell the childOrganism what environment it belongs to
            _organisms.hostEnvironment = hostEnvironment;

            // tell the childOrganism what group of organisms it belongs to
            _organism.Organisms = _organisms;

            _simEnv.TraceLogger.LogDebug("Loading Organisms - End");

            return hostEnvironment;
        }



        /// <summary>
        /// Saves the organisms back to the database
        /// </summary>
        /// <param name="environment"></param>
        /// <param name="hostEnvironment"></param>
        /// <returns></returns>
        public bool SaveHostingEnvironment(string environment, IHostingEnvironment hostEnvironment, int maxSaveCount)
        {
            _simEnv.TraceLogger.LogDebug(string.Format("Total Organisms {0}", hostEnvironment.Organisms.Alive.Count + hostEnvironment.Organisms.Dead.Count + hostEnvironment.Organisms.Inactive.Count));
            _simEnv.TraceLogger.LogDebug(string.Format("Alive Organisms {0}", hostEnvironment.Organisms.Alive.Count));
            _simEnv.TraceLogger.LogDebug(string.Format("Dead Organisms {0}", hostEnvironment.Organisms.Dead.Count));
            _simEnv.TraceLogger.LogDebug(string.Format("Inactive Organisms {0}", hostEnvironment.Organisms.Inactive.Count));
            _simEnv.TraceLogger.LogDebug("SaveOrganisms, The method or operation is not implemented.");

            return true;
        }
    }
}